from webob import Request, Response
from pylons import request as pylons_request
from pprint import pformat

import logging
log = logging.getLogger(__name__)

class AuthorityMethodError(Exception):pass

class AuthMethod(object):
    '''Base class for Authority AuthMethods
    
    '''
    def __init__(self, method_opts = None):
        method_opts = method_opts or {}
        self.options = method_opts
    
    def get_credentials(self, environ):
        raise NotImplementedError
        
    def make_prompt(self):
        raise NotImplementedError
    
class HTTPBasicAuthMethod(AuthMethod):
    '''Authenticate using HTTP Basic Authentication
    
    '''

    def get_credentials(self, environ):      
        auth_header = environ.get('HTTP_AUTHORIZATION')
        if not auth_header:
            log.debug('auth header NOT found')
            return None
        else:
            log.debug('auth header found')
            auth_type, encoded_info = auth_header.split(None, 1)
            if auth_type.lower() != 'basic':
                log.debug('Unknown Authentication Type: %s'%auth_type)
                raise AuthorityMethodError('Unknown Authentication Type: %s'%auth_type)
            unencoded_info = encoded_info.decode('base64')
            username, password = unencoded_info.split(':', 1)
            log.debug('user = %s' % username)
            log.debug('pass = %s' % password)
            cred = dict()
            cred['user'] = username
            cred['password'] = password
            return cred

    def make_prompt(self):
        
        http401_page_body = """
            <html>
             <head><title>Authentication Required</title></head>
             <body>
              <h1>Authentication Required</h1>
              If you can't get in, then stay out.
             </body>
            </html>"""
            
        if self.options.has_key('realm'):
            realm = self.options['realm']
        else:
            default_realm = "Authority Realm"
            realm = default_realm
        
        response = Response(body=http401_page_body, 
                            content_type='text/html')
        response.status = '401 Authentication Required'
        response.headers['WWW-Authenticate'] = 'Basic realm="%s"' % realm
        log.debug('basic auth response header:')
        log.debug(pformat(response.headers))

        return response
        
class AuthFormMethod(AuthMethod):
    '''Authenticate using a form generated by Authority
    
    '''
    def get_credentials(self, environ):  
        req = Request(environ)
        if req.method == 'POST':
            cred = dict()
            cred['user'] = req.POST['username']
            cred['password'] = req.POST['password']
            return cred
        return None

    def _get_form(self):
        form = '''
            <html>
            <head><title>Authority Form Page</title></head>
            <body>
            
            <h1>Authority Login Form</h1>
            <form action="/private" method = "post">
                <label>Username: </label>
                <input type="text" name="username"><br>
                <label>Password:</label>
                <input type="password" name="password"><br>
                <input type="submit" value="Login">
            </form>
            
            </body>
            </html>
            '''
        return form

    def make_prompt(self):
        authform_page = self._get_form()
        response = Response(body=authform_page)
        #~ ,
                            #~ content_type='text/html')
        return response
        
        
class AppFormMethod(AuthMethod):
    '''Authenticate using a form provided by the wrapped application
    
    '''
    def get_credentials(self, environ):  
        req = Request(environ)
        if req.method == 'POST':
            cred = dict()
            cred['user'] = req.POST['username']
            cred['password'] = req.POST['password']
            return cred
        return None
        
    def _get_form(self):
        pass
        
    def make_prompt(self):
        env = pylons_request.environ
        req = Request(env)
        req.path_info = "/loginform"
        resp = req.get_response(self.scheme.app)
        return resp
    
    
